const CryptoJS = require('crypto-js');  //引用AES源码js
const config = require('./config');
const fs = require("fs-extra");
const path = require("path");
const xlsx = require("node-xlsx");

var util = {
    //解密方法
    Decrypt: function Decrypt(word, keyType) {
        try {
            var key = CryptoJS.enc.Utf8.parse(config[keyType].key);  //十六位十六进制数作为密钥
            var iv = CryptoJS.enc.Utf8.parse(config[keyType].iv);   //十六位十六进制数作为密钥偏移量

            let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
            let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
            let decrypt = CryptoJS.AES.decrypt(srcs, key, {
                iv: iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
            return decryptedStr.toString();
        } catch (e) {
            console.log(e)
            return '';
        }
    },

    //加密方法
    Encrypt: function Encrypt(word, keyType) {
        try {
            var key = CryptoJS.enc.Utf8.parse(config[keyType].key);  //十六位十六进制数作为密钥
            var iv = CryptoJS.enc.Utf8.parse(config[keyType].iv);   //十六位十六进制数作为密钥偏移量

            let srcs = CryptoJS.enc.Utf8.parse(word);
            let encrypted = CryptoJS.AES.encrypt(srcs, key, {
                iv: iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            return encrypted.ciphertext.toString().toUpperCase();
        } catch (e) {
            console.log(e);
            return '';
        }

    },

    getEncryptMsg: function (params, keyType) {
        if (!params.data) return null;
        try {
            let aesParams = util.Decrypt(params.data, keyType);
            return JSON.parse(aesParams)
        } catch (e) {
            return null;
        }

    },

    validAdminToken: function (req, res) {
        try {
            let webAuthorization = req.get("webAuthorization");
            let webMsg = util.Decrypt(webAuthorization, 'token');
            webMsg = JSON.parse(webMsg);
            let now = new Date().getTime();
            console.log('now', now)
            console.log('lastTime', webMsg.lastTime)
            if (webMsg.lastTime && Number(webMsg.lastTime) > now) {
                return true;
            } else {
                res.send({
                    code: -6,
                    message: '登录超时，请重新登录'
                })
                return false;
            }
        } catch (e) {
            res.send({
                code: -6,
                message: '登录超时，请重新登录'
            })
            return false;
        }
    },

    // 文件夹是否存在, 不存在则创建文件
    folderIsExit: function (folder) {
        console.log('folderIsExit', folder)
        return new Promise((resolve, reject) => {
            fs.ensureDir(folder, err => {
                console.log('result----', err)
                resolve(true)
            })
        })
    },

    // 文件或文件夹是否存在
    isExist: function (filePath) {
        return new Promise((resolve, reject) => {
            fs.stat(filePath, (err, stats) => {
                // 文件不存在
                if (err && err.code === 'ENOENT') {
                    resolve(false)
                } else {
                    resolve(true)
                }
            })
        })
    },

    // 列出文件夹下所有文件
    listDir(path) {
        return new Promise((resolve, reject) => {
            fs.readdir(path, (err, data) => {
                if (err) {
                    reject(err)
                    return
                }
                // 把mac系统下的临时文件去掉
                if (data && data.length > 0 && data[0] === '.DS_Store') {
                    data.splice(0, 1)
                }
                resolve(data)
            })
        })
    },

    // 把文件从一个目录拷贝到别一个目录
    copyFile(src, dest) {
        let promise = new Promise((resolve, reject) => {
            fs.rename(src, dest, err => {
                if (err) {
                    reject(err)
                } else {
                    resolve('copy file:' + dest + ' success!')
                }
            })
        })
        return promise
    },

    publicPath() {
        return path.resolve(__dirname, '../', ...arguments)
    },

    /**
     * 创建下载文件对象
     * @param res，response对象
     * @param filePath，文件路径
     * @param fileName，文件名称
     * @return Promise
     */
    createDownloadFile: function (res, filePath, fileName) {
        fileName = encodeURI(fileName, "GBK")
        fileName = fileName.toString('iso8859-1')
        return new Promise((resolve, reject) => {
            try{
                const stats = fs.statSync(filePath);
                res.writeHead(200, {
                    "Content-Type": "application/octet-stream", //告诉浏览器这是一个二进制文件
                    "Content-Disposition": "attachment; filename=" + fileName, //告诉浏览器这是一个需要下载的文件
                    "Content-Length": stats.size, //文件大小
                });
                const readStream = fs.createReadStream(filePath);
                readStream.pipe(res);
                readStream.on('end', () => {
                    resolve('success');
                });
            }catch (e) {
                reject(e);
            }
        })
    },

    /**
     * sql数据转换为excel
     * @param columns，excel表头
     * @param data，sql数据
     * @param filePath，文件路径
     */
    sqlData2Excel: function (columns, data, filePath, folderPath) {
        let tableData = [columns];
        for (let i = 0; i < data.length; i++) {
            let arr = [];
            let value = data[i];
            for (let j in value) {
                arr.push(value[j]);
            }
            tableData.push(arr);
        }
        const buffer = xlsx.build([
            {
                name: 'sheet1',
                data: tableData
            }
        ]);
        return new Promise((resolve, reject) => {
            // 判断文件夹是否存在
            util.folderIsExit(filePath.substring(0, filePath.lastIndexOf('/'))).then(() => {
                fs.writeFile(filePath, buffer, {'flag': 'w'}, function (err) {
                    if (!err) {
                        return resolve();
                    }
                    reject(err);
                });
            }).catch((err) => {
                reject(err);
            })
        })

    },

    responseSuccess({res, message, data}){
        try{
            let response = {
                message:message || 'success',
                success:true,
            }
            if(data){
                response.data=data
            }
            res.json(response)
        }catch(e){
            console.log(e)
        }
    },

    responseFailure({res, message}){
        try{
            let response = {
                message:message || 'failure',
                success:false,
            }
            res.json(response)
        }catch(e){
            console.log(e)
        }
    },

    // 校验对象中的key对应的值是否为空
    validListNull(data,keyList){
        keyList.forEach(key=>{
            if(!data[key]){
                return {
                    status:false,
                    key:key
                }
            }
        })
        return {
            status: true
        }
    },

    /**
     * uuid
     * @param len，长度
     * @param radix，基数
     * */
    uuid(len, radix) {
        const chars = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
        let uuid = [];
        radix = radix || chars.length;

        if (len) {
            // Compact form
            for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
        } else {
            // rfc4122, version 4 form
            let r;

            // rfc4122 requires these characters
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
            uuid[14] = '4';

            // Fill in random data.  At i==19 set the high bits of clock sequence as
            // per rfc4122, sec. 4.1.5
            for (let i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random()*16;
                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                }
            }
        }

        return uuid.join('');
    }
}

module.exports = util;
